#include "lv_drv_conf.h"

#if USE_CRANE_JPU

#include "stdio.h"

#include "../common/utils.h"
#include "../../board.h"
#include "../common/media_clock.h"
#include "crane_jpuc_common.h"

struct jpu_device jpu_dev =
{
    JPU_STATE_BOOT,
    IRQ_MMP_CAM_JPEG,
    0,
};

#if USE_CRANE_CAMERA
uint8_t jpeg_encode_flag = MAX_FLAG_NUM;
#endif

uint8_t jpeg_decode_flag = MAX_FLAG_NUM;
uint16_t jpeg_decode_reg = 0;

static void _JpegIntrHandler(void *arg)
{
    uint32_t val = jpu_read(MJPEG_PIC_STATUS_REG);

    jpu_write(MJPEG_PIC_STATUS_REG, val);

    if (val & MJPEG_HW_IRQ_STATUS_CODEC_START) {
//        printf("---jpeg sof\n");
    }

    if (val & MJPEG_HW_IRQ_STATUS_CONFIG_DONE) {
//        printf("---cfg.done\n");
    }

    if (val & MJPEG_HW_IRQ_STATUS_DECODE_ERROR) {
//        printf("---jpeg.error\n");
    }

    if (val & MJPEG_HW_IRQ_STATUS_PARTIAL_OVERFLOW) {
//        printf("---jpeg.overflow\n");
    }

    if (val & MJPEG_HW_IRQ_STATUS_CODEC_DONE) {
        /*uint32_t ptr = */jpu_read(LAST_MJPEG_BBC_WR_PTR_REG);
//        printf("---jpeg.eof,[0x%08x]=0x%08x,WR_PTR=0x%08x\n", ptr & 0xFFF00000, readl(ptr & 0xFFF00000), ptr);
    }
#if USE_CRANE_CAMERA
    uint8_t rc = 0;
    if (JPU_STATE_ENC_ACTIVE == jpu_dev.state) {
        rc = uos_set_flag(jpeg_encode_flag, val, UOS_FLAG_OR);
        if (rc != 0)
            printf("jpuenc flag set error\n");
    }
#endif
    if (JPU_STATE_DEC_ACTIVE == jpu_dev.state) {
        if(jpeg_decode_flag != MAX_FLAG_NUM) {
            uos_set_flag(jpeg_decode_flag, val, UOS_FLAG_OR);
        } else {
            jpeg_decode_reg = val;
        }
    }

}

static uint32_t _jpu_register_irq(void)
{
    register_int_handler(jpu_dev.irq, (int_handler)_JpegIntrHandler, NULL);

    return IRQ_MMP_CAM_JPEG;
}

void jpu_irq_enable(void)
{
    unmask_interrupt(jpu_dev.irq);
}

void jpu_irq_disable(void)
{
    mask_interrupt(jpu_dev.irq);
}

int jpu_common_init(void)
{
    if (jpu_dev.state != JPU_STATE_BOOT) {
//        printf("JPU have been inited!\n");
        return -1;
    }
#if USE_CRANE_CAMERA
    jpeg_encode_flag = uos_create_flag();
#endif
    _jpu_register_irq();
    jpu_dev.jpu_open_cnt = 0;
    jpu_dev.state = JPU_STATE_IDLE;
//    printf("%s\n", __FUNCTION__);

    return 0;
}

void jpu_clk_reset(void)
{
    pmu_clear_bits(0x50, BIT_15);
    pmu_set_bits(0x50, BIT_15);
}

void media_clk_jpu_on(void)
{
    media_clock_power_on(MODULE_CAMERA);

    media_clock_enable(MEDIA_CLK_LCD_CI, MODULE_CAMERA); /* MEDIA_CLK_LCD_AHB depend on MEDIA_CLK_LCD_CI */
    media_clock_enable(MEDIA_CLK_LCD_AHB | MEDIA_CLK_OFFLINE_AXI, MODULE_CAMERA);
    media_clock_enable(MEDIA_CLK_JPEG_FUNC, MODULE_CAMERA);
    media_clock_enable(MEDIA_CLK_INTERFACE, MODULE_CAMERA);
}

void media_clk_jpu_off(void)
{
    media_clock_disable(MEDIA_CLK_INTERFACE, MODULE_CAMERA);
    media_clock_disable(MEDIA_CLK_JPEG_FUNC, MODULE_CAMERA);
    media_clock_disable(MEDIA_CLK_LCD_AHB | MEDIA_CLK_OFFLINE_AXI, MODULE_CAMERA);
    media_clock_disable(MEDIA_CLK_LCD_CI, MODULE_CAMERA);

    media_clock_power_off(MODULE_CAMERA);
}

#endif

